package com.css.bjdt_report.executive.util;

import java.util.List;
import java.util.Map;

import com.css.bjdt_report.cell.entity.Cell;
import com.css.bjdt_report.executive.entity.Exp;
import com.css.bjdt_report.executive.entity.IType;
import com.css.bjdt_report.util.ReportConstant;
/**
 * 
 * 1.前台行计算表达式:1行=2行+3行;前台列计算表达式:A列=B列+C列;前台单元格计算表达式:A1=B1+C1;
 * 2.后台行计算表达式:1行=2行+3行;后台列计算表达式:1列=2列+3列;后台单元格计算表达式:[1_1]=[1_2]+[1_3];
 * 3.前台行校核表达式:1行=2行+3行;前台列校核表达式:A列=B列+C列;前台表内单元格校核表达式:A1=B1+C1;前台表间单元格校核表达式:表1.A1=表2.A2+表3.A3;
 * 4.后台行校核表达式:1行=2行+3行;后台列校核表达式:1列=2列+3列;后台表内表间单元格校核表达式:指标1的id=指标2的id+指标3的id;
 * 
 */
public abstract class ExpParser {
	//以计算类型为key
	private Map<String,List<Exp>> expMap;
	/**
	 * 解析计算表达式
	 * @param cell
	 */
	public abstract void parseExp(Cell cell);
	/**
	 * 转换表达式通用方法
	 * @param cell
	 * @param type
	 */
	private void convertExpToCellExp(Cell cell, String type) {
		List<Exp> exps = expMap.get(type);
		if (exps != null && exps.size() > 0) {
			for (Exp exp : exps) {
				String formula = exp.getFormula();
				// 存储原表达式
				cell.setOldExp(formula);
				// 按关系运算符(><=)拆分
				String[] array = formula.split(ReportConstant.OPERATOR_RELA);
				// 判断计算表达式拆分完成后是否为2部分
				if (array.length == 2) {
					// 等号前面部分为计算指标的行号或列号
					String resultNum = getNumber(array[0]);
					// 等号后面部分为参加计算的指标表达式
					String calcExp = array[1];
					// 按算数运算符(+-*/)拆分
					String[] calcNums = calcExp.split(ReportConstant.OPERATOR_ARITH);
					// 如果计算类型为行计算且指标的行号等于计算指标的行号,那么遍历并替换行表达式为单元格表达式
					if (IType.TABLE_INNER_ROW.equals(type) && cell.getRowNum().toString().equals(resultNum)) {
						for (String calcNum : calcNums) {
							// 替换成:[行号+拆分符+列号]
							StringBuilder sb = new StringBuilder();
							sb.append("[").append(getNumber(calcNum)).append(ReportConstant.SPLIT_OPERATOR).append(cell.getColNum()).append("]");
							calcExp = calcExp.replaceFirst(calcNum, sb.toString());
						}
					}
					// 如果计算类型为列计算且指标的列号等于计算指标的列号,那么遍历并替换列表达式为单元格表达式
					else if (IType.TABLE_INNER_COL.equals(type) && cell.getColNum().toString().equals(resultNum)) {
						for (String calcNum : calcNums) {
							StringBuilder sb = new StringBuilder();
							sb.append("[").append(cell.getRowNum()).append(ReportConstant.SPLIT_OPERATOR).append(getNumber(calcNum)).append("]");
							calcExp = calcExp.replaceFirst(calcNum, sb.toString());
						}
					}
					// 如果计算类型为单元格计算且指标的行号与列号等于计算指标的行号与列号,那么不做处理
					else if (IType.TABLE_INNER_CELL.equals(type) && array[0].equals(cell.getRowNum() + ReportConstant.SPLIT_OPERATOR + cell.getColNum())) {

					} else {
						calcExp = null;
					}
					if (calcExp != null) {
						cell.setCalcExp(calcExp);
						handleResult(cell, exp);
					}
				}
			}
		}
	}

	public abstract void handleResult(Cell cell, Exp exp);
	
	/**
	 * 转换行表达式为单元格表达式eg:1行=2行+3行->1_1=2_1+3_1
	 * @param cell
	 */
	public void handleRowExp(Cell cell){
		convertExpToCellExp(cell, IType.TABLE_INNER_ROW);
	}
	/**
	 * 转换列表达式为单元格表达式eg:1列=2列+3列->1_1=1_2+1_3
	 * @param cell
	 */
	public void handleColExp(Cell cell){
		convertExpToCellExp(cell, IType.TABLE_INNER_COL);		
	}
	/**
	 * 
	 * @param cell
	 */
	public void handleCellExp(Cell cell){
		convertExpToCellExp(cell, IType.TABLE_INNER_CELL);		
	}
	/**
	 * 去掉后缀获取数字eg:1行->1;2列->2
	 * @param str
	 * @return
	 */
	private String getNumber(String str){
		if(str.endsWith(ReportConstant.ROW_ZH_CN) || str.endsWith(ReportConstant.COL_ZH_CN)){
			return str.substring(0, str.length()-1);
		}
		return str;
	}

	public void setExpMap(Map<String, List<Exp>> expMap) {
		this.expMap = expMap;
	}
	
	public void destory(){
		if(expMap != null){
			expMap.clear();
			expMap = null;
		}
	}
}
